import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd/message';
import { ApiService } from 'src/app/services/api.service';
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree';
import { DeptDto } from 'src/app/models/sys/dept.dto';
import { Consts } from 'src/app/consts/consts';
import { DeptQueryParam } from 'src/app/models/param/dept-query.param';
import { DictDto } from 'src/app/models/sys/dict.dto';
import { TreeUtils } from 'src/app/utils/tree.util';
import { AddUserParam } from 'src/app/models/param/add-user.param';
import { UserDto } from 'src/app/models/sys/user.dto';
import { BehaviorSubject } from 'rxjs';
import { EditMode } from 'src/app/models/enums/edit-mode.enum';
import { UpdateUserParam } from 'src/app/models/param/update-user.param';
import { PostDto } from 'src/app/models/sys/post.dto';
import { PostQueryParam } from 'src/app/models/param/post-query.param';
import { RoleDto } from 'src/app/models/sys/role.dto';
import { RoleQueryParam } from 'src/app/models/param/role-query.param';

const USERNAME = 'username';
const PASSWORD = 'password';
const NICK_NAME = 'nickName';
const DEPT_ID = 'deptId';
const PHONE_NUMBER = 'phoneNumber';
const EMAIL = 'email';
const SEX = 'sex';
const ENABLED = 'enabled';
const REMARK = 'remark';
const POST = 'post';
const ROLE = 'role';
const JOIN_TIME = 'joinTime';
const BIRTHDAY = 'birthday';

@Component({
  selector: 'app-add-employee',
  templateUrl: './add-employee.component.html',
  styleUrl: './add-employee.component.less'
})
export class AddEmployeeComponent implements OnInit {
  @Input() modeSubject!: BehaviorSubject<{ mode: EditMode, user?: UserDto }>;
  @Output() addEmployeeEvent = new EventEmitter<boolean>();

  // 先写死
  avatar = 'https://cms-1255717697.cos.ap-chengdu.myqcloud.com/assets/20231206/qq.png';

  user?: UserDto;
  modeEnum = EditMode;
  editMode = EditMode.ADD;

  // form fields
  addForm!: UntypedFormGroup;
  submitted = false;

  depts: DeptDto[] = [];
  deptNodes: NzTreeNodeOptions[] = [];
  selectedNode?: string;

  passwordVisible = false;
  expandKeys = [];

  selectedEnabled = true;

  sexes: DictDto[] = [];
  posts: PostDto[] = [];
  roles: RoleDto[] = [];
  selectedRoleIds: number[] = [];

  constructor(private _api: ApiService,
    private _fb: FormBuilder,
    private _message: NzMessageService) {
    this.onReset();
  }

  ngOnInit(): void {
    console.log('Add Employ OnInit');
    this.createAddForm();
    this.getSexTypes();
    this.getDepts();
    this.getPosts();
    this.getRoles();
  }

  onReset() {
    this.user = undefined;
    this.editMode = EditMode.ADD;
    this.submitted = false;
    this.depts = [];
    this.deptNodes = [];
    this.selectedNode = undefined;
    this.expandKeys = [];
    this.sexes = [];
  }

  createAddForm() {
    this.addForm = this._fb.group({
      username: new FormControl('', [Validators.minLength(2), Validators.maxLength(40)]),
      password: new FormControl('', [Validators.minLength(6), Validators.maxLength(45)]),
      nickName: new FormControl('', [Validators.minLength(2), Validators.maxLength(40)]),
      deptId: new FormControl(''),
      phoneNumber: new FormControl(''),
      email: new FormControl(''),
      sex: new FormControl(''),
      enabled: new FormControl(''),
      remark: new FormControl(''),
      post: new FormControl(''),
      birthday: new FormControl(''),
      joinTime: new FormControl(''),
    });

    this.modeSubject.subscribe((value) => {
      this.editMode = value.mode;

      if (this.editMode == EditMode.ADD) {
        console.log('Add Employee modal in Add Mode');
        this.addForm.get(USERNAME)?.addValidators([Validators.required]);
        this.addForm.get(PASSWORD)?.addValidators([Validators.required]);
      } else {
        console.log('Add Employee modal in Edit Mode');
        this.user = value.user!;
        this.initParam(this.user);
      }
    });
  }

  initParam(user: UserDto) {
    console.log(`Input with user ${user.username}`);
    this.addForm.get(USERNAME)?.patchValue(user.username);
    console.log(`patch ${USERNAME} to ${user.username}`);
    this.addForm.get(USERNAME)?.disable();
    this.addForm.get(USERNAME)?.clearValidators();

    this.addForm.get(PASSWORD)?.clearValidators();
    this.addForm.get(PASSWORD)?.disable();

    this.addForm.patchValue({ nickName: user.nickName });
    console.log(`patch ${NICK_NAME} to ${user.nickName}`);
    //         this.addForm.get('nickName')?.patchValue(user.nickName);
    this.selectedNode = user.deptId?.toString();

    this.addForm.get(PHONE_NUMBER)?.patchValue(user.phoneNumber);
    this.addForm.get(EMAIL)?.patchValue(user.email);
    this.addForm.get(SEX)?.patchValue(user.sex);
    console.log(`patch enabled to ${user.enabled}`);
    this.addForm.get(ENABLED)?.patchValue(user.enabled);
    this.addForm.get(REMARK)?.patchValue(user.remark);
    this.addForm.get(JOIN_TIME)?.patchValue(user.joinTime);
    this.addForm.get(BIRTHDAY)?.patchValue(user.birthday);
  }

  getSexTypes() {
    this._api.getSexType().subscribe((resp) => {
      if (resp.code == Consts.RESP_OK && resp.data) {
        this.sexes = resp.data;
        console.log(`Sex has ${this.sexes.length} items`);
      }
    });
  }

  getDepts() {
    const param = new DeptQueryParam();
    param.pageNum = 1;
    param.pageSize = 10000;
    this._api.getDeptTree(param).subscribe((resp) => {
      if (resp.code == Consts.RESP_OK && resp.data) {
        this.depts = resp.data;
        this.deptNodes = TreeUtils.convertDeptToTreeNodes(this.depts);
      }
    });
  }

  getPosts() {
    const param = new PostQueryParam();
    param.pageNum = 1;
    param.pageSize = 10000;
    this._api.getPostList(param).subscribe((resp) => {
      if (resp.code == Consts.RESP_OK && resp.data) {
        this.posts = resp.data;
      }
    });
  }

  getRoles() {
    const param = new RoleQueryParam();
    param.pageNum = 1;
    param.pageSize = 10000;
    this._api.getRoleList(param).subscribe((resp) => {
      if (resp.code == Consts.RESP_OK && resp.data) {
        this.roles = resp.data;
      }
    });
  }

  get fm() {
    return this.addForm.controls;
  }

  onAction(event: UIEvent) {
    if (this.editMode == this.modeEnum.ADD) {
      this.onCreate(event);
    } else {
      this.onUpdate(event);
    }
  }

  onCreate(event: UIEvent) {
    event.preventDefault();
    this.submitted = true;
    if (this.addForm.invalid) {
      console.log('form error');
      return;
    }

    const param = new AddUserParam();
    param.username = this.addForm.get(USERNAME)?.value;
    param.password = this.addForm.get(PASSWORD)?.value;
    param.nickName = this.addForm.get(NICK_NAME)?.value;
    // param.deptId = this.addForm.get(DEPT_ID)?.value;
    param.phoneNumber = this.addForm.get(PHONE_NUMBER)?.value;
    param.email = this.addForm.get(EMAIL)?.value;
    param.sex = this.addForm.get(SEX)?.value;
    // param.enabled = this.addForm.get(ENABLED)?.value;
    param.remark = this.addForm.get(REMARK)?.value;
    param.joinTime = this.addForm.get(JOIN_TIME)?.value;
    param.birthday = this.addForm.get(BIRTHDAY)?.value;
    if (this.selectedRoleIds != undefined && this.selectedRoleIds.length > 0) {
      param.roleIds = this.selectedRoleIds;
    }

    // 先写死
    param.avatar = this.avatar;

    param.deptId = this.selectedNode;
    param.enabled = this.selectedEnabled;

    this._api.addUser(param).subscribe((resp) => {
      if (resp.code == Consts.RESP_OK) {
        this._message.info("Add User OK");
        this.addEmployeeEvent.emit(true);
      } else {
        this._message.warning("Add User Error " + resp.message);
      }
    });
  }

  onUpdate(event: UIEvent) {
    event.preventDefault();
    this.submitted = true;
    if (this.addForm.invalid) {
      console.log('form error');
      return;
    }

    const param = new UpdateUserParam();
    param.userId = this.user!.userId;
    param.nickName = this.addForm.get(NICK_NAME)?.dirty ? this.addForm.get(NICK_NAME)?.value : undefined;
    param.deptId = this.addForm.get(DEPT_ID)?.dirty ? this.addForm.get(DEPT_ID)?.value : undefined;
    param.phoneNumber = this.addForm.get(PHONE_NUMBER)?.dirty ? this.addForm.get(PHONE_NUMBER)?.value : undefined;
    param.email = this.addForm.get(EMAIL)?.dirty ? this.addForm.get(EMAIL)?.value : undefined;
    param.sex = this.addForm.get(SEX)?.dirty ? this.addForm.get(SEX)?.value : undefined;
    param.enabled = this.addForm.get(ENABLED)?.dirty ? this.addForm.get(ENABLED)?.value : undefined;
    param.remark = this.addForm.get(REMARK)?.dirty ? this.addForm.get(REMARK)?.value : undefined;
    param.joinTime = this.addForm.get(JOIN_TIME)?.dirty ? this.addForm.get(JOIN_TIME)?.value : undefined;
    param.birthday = this.addForm.get(BIRTHDAY)?.dirty ? this.addForm.get(BIRTHDAY)?.value : undefined;

    this.doUpdate(param);
  }

  doUpdate(param: UpdateUserParam) {
    this._api.updateUser(param).subscribe((resp) => {
      if (resp.code == Consts.RESP_OK) {
        this._message.info("Update User OK");
        this.addEmployeeEvent.emit(true);
      } else {
        this._message.warning("Update User Error " + resp.message);
      }
    });
  }

  onCancel(event: UIEvent) {
    event.preventDefault();
    console.log('onCancel');
    this.onReset();
    this.addEmployeeEvent.emit(false);
  }

  onChange(event: string): void {
    const selected = this.addForm.get('deptId');
    console.log(`selected node ${selected} with event ${event}`);
  }
}
